package com.treasure.mall.biz.service.core.log.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.dto.condition.AdvanceLogSearchCondition;
import com.treasure.mall.biz.dto.user.ModifyBalanceDTO;
import com.treasure.mall.biz.entity.log.AdvanceLogPO;
import com.treasure.mall.biz.entity.log.AdvanceLogPO_;
import com.treasure.mall.biz.repository.log.AdvanceLogRepository;
import com.treasure.mall.biz.service.core.log.AdvanceLogService;
import com.treasure.mall.zbq.common.StringUtilsExt;
import com.treasure.mall.zbq.common.ienum.base.CodeDescEnumHelper;
import com.treasure.mall.zbq.common.ienum.log.AdvanceLogType;
import com.treasure.mall.zbq.common.ienum.log.LogDataType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author guomw
 * @version 1.0
 * @date 2019/10/19 00:43
 */
@Service
public class AdvanceLogServiceImpl extends AbstractSearchableCrudService<AdvanceLogPO, Long> implements AdvanceLogService {

    private AdvanceLogRepository advanceLogRepository;

    @Autowired
    protected AdvanceLogServiceImpl(AdvanceLogRepository repository) {
        super(repository);
        advanceLogRepository = repository;
    }

    @Override
    protected SpecificationAndSort<AdvanceLogPO> specificationAndSort(BaseSearchDTO searchDTO) {
        AdvanceLogSearchCondition condition = (AdvanceLogSearchCondition) searchDTO;
        Specification<AdvanceLogPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            //根据数据类型查询

            // 收入类型 支出和收入
            if (condition.getIncome() != null) {

                boolean flag = condition.getDataType() == null;
                if (!flag) {
                    flag = condition.getDataType().getCode().equals(LogDataType.BALANCE.getCode());
                }
                if (flag) {
                    if (condition.getIncome()) {
                        predicates.add(cb.greaterThan(root.get(AdvanceLogPO_.amount), BigDecimal.valueOf(0)));
                    } else {
                        predicates.add(cb.lessThan(root.get(AdvanceLogPO_.amount), BigDecimal.valueOf(0)));
                    }
                }
            }

            if (condition.getDataType() != null) {
                predicates.add(cb.equal(root.get(AdvanceLogPO_.dataType), condition.getDataType()));
            }


            if (!StringUtils.isEmpty(condition.getOrderId())) {
                predicates.add(cb.equal(root.get("orderId").as(String.class), condition.getOrderId()));
            }
            if (condition.getLogType() > -1) {
                AdvanceLogType advanceLogType = CodeDescEnumHelper.getEnumTypeByCode(AdvanceLogType.class, condition.getLogType());
                predicates.add(cb.equal(root.get("logType").as(AdvanceLogType.class), advanceLogType));
            }
            if (condition.getUserId() > 0) {
                predicates.add(cb.equal(root.get("userId").as(Long.class), condition.getUserId()));
            }
            if (!StringUtils.isEmpty(condition.getBeginTime())) {
                LocalDateTime beginTime = StringUtilsExt.localDateTimeFormat(condition.getBeginTime());
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), beginTime));
            }
            if (!StringUtils.isEmpty(condition.getEndTime())) {
                LocalDateTime endTime = StringUtilsExt.localDateTimeFormat(condition.getEndTime());
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), endTime));
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "logId");

        return new SpecificationAndSort<>(specification, sort);
    }

    @Override
    public AdvanceLogPO save(BaseSaveDTO saveDTO) {
        return null;
    }

    @Override
    public AdvanceLogPO save(AdvanceLogPO advanceLogPO) {
        return advanceLogRepository.save(advanceLogPO);
    }

    @Override
    public AdvanceLogPO save(ModifyBalanceDTO modifyBalanceDTO, LogDataType dataType, BigDecimal before, BigDecimal after) {
        //记录日志
        AdvanceLogPO advanceLogPO = new AdvanceLogPO();
        advanceLogPO.setUserId(modifyBalanceDTO.getId());
        advanceLogPO.setDataType(dataType);
        advanceLogPO.setLogType((AdvanceLogType) modifyBalanceDTO.getLogType());
        advanceLogPO.setAmount(modifyBalanceDTO.getAmount());
        advanceLogPO.setBeforeAmount(before);
        advanceLogPO.setAfterAmount(after);
        advanceLogPO.setOrderId(modifyBalanceDTO.getOrderId());
        advanceLogPO.setCreateTime(LocalDateTime.now());
        advanceLogPO.setOpId(modifyBalanceDTO.getOpId());
        advanceLogPO.setOpName(modifyBalanceDTO.getOpName());
        advanceLogPO.setRemark(modifyBalanceDTO.getRemark());
        advanceLogRepository.save(advanceLogPO);
        return advanceLogPO;
    }
}
